Skip to content

fix(cli): resolve raw binary asset for Windows self-update, not *-setup#13

Merged
MichaelTaylor3d merged 1 commit into
mainfrom
fix/303-windows-self-update
Jul 11, 2026
Merged

fix(cli): resolve raw binary asset for Windows self-update, not *-setup#13
MichaelTaylor3d merged 1 commit into
mainfrom
fix/303-windows-self-update

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

What

digstore update on Windows returned NotFound because the Windows self-update path called select_installer_asset, which looked for a bundled *-setup.exe/.msi GUI installer. That installer moved to dig-installer, so digstore's own releases no longer publish one — the lookup always found nothing.

Fixes #303.

How

Unified the Windows update path with the existing macOS/Linux self-replace path — digstore now updates ITS OWN binary in place on every platform, no GUI installer step:

  • perform_update no longer branches on #[cfg(target_os = "windows")] vs not; one path resolves the raw digstore-<ver>-windows-x64.exe (or per-OS/arch equivalent) asset via select_binary_asset, downloads it, sanity-checks the magic bytes, then calls install_binary.
  • install_binary gained a Windows-specific step: a direct one-step overwrite of the currently-executing binary fails on Windows (Access is denied, os error 5), even though Windows lets you rename a running image aside. So on Windows: rename the current binary aside → rename the new one into place → best-effort delete the old one (harmless if it's still locked; it's never the active target path again).
  • fetch_bytes is no longer cfg-gated off Windows (shared download path for every platform).
  • Removed the now-dead select_installer_asset/select_windows_installer/download_asset/launch_installer GUI-installer helpers and their tests (gitnexus confirmed select_installer_asset had exactly one caller, perform_update, in this same file — LOW risk, no other consumers in the repo).

Verified

  • RED first: added a test that spawns a copy of ping.exe, keeps it running as a child process, then calls install_binary on that locked file — against the pre-fix code this failed with UpdateFailed("... Access is denied (os error 5) ..."), reproducing the exact class of bug reported (a plain rename over a currently-executing file fails on Windows). Confirmed RED, then implemented the fix, confirmed GREEN.
  • New unit test selects_windows_x64_raw_binary asserts the shared selector resolves digstore-<ver>-windows-x64.exe (not *-setup.exe/.msi) from the real release asset-name fixture.
  • cargo fmt -p digstore-cli --check: clean.
  • cargo clippy -p digstore-cli --all-targets --all-features -- -D warnings: clean.
  • cargo clippy --workspace --all-targets --locked -- -D warnings <CI's two allowed lints>: clean (exact CI command).
  • cargo build --workspace --locked: clean.
  • cargo test -p digstore-cli --lib: 268 passed, 0 failed, 1 ignored (live-network smoke test, intentionally #[ignore]d).
  • cargo test -p digstore-cli --tests: full installed-crate integration suite green (every tests/*.rs file), 0 failed.
  • §3.5: reinstalled via cargo install --path crates/digstore-cli --force --lockeddigstore --version reports the new 0.11.1; ran digstore update --check against the live GitHub API with the reinstalled binary — completes cleanly (already up to date (v0.11.1)), no regression in the surrounding command.
  • detect_changes (gitnexus): risk low, 0 affected downstream execution flows — every changed symbol is contained in crates/digstore-cli/src/commands/update.rs.

Full-workspace cargo test --workspace link phase could not complete locally due to the dev sandbox running low on disk (unrelated pre-existing environment constraint on this shared machine, not caused by this change); the scoped crate build/lint/test gates above are exhaustive for the change's actual blast radius, and CI's --workspace gate will run authoritatively on this PR.

Blast radius

gitnexus impact({target: "select_installer_asset", direction: "upstream"}): LOW risk, single caller (perform_update), same file — confirmed no other consumers exist anywhere in the repo (suggest_manual_asset/select_binary_asset/fetch_bytes/install_binary/resolve_self_path similarly grepped clean of any cross-module callers). Change is fully contained to crates/digstore-cli/src/commands/update.rs.

Version bump

Patch: 0.11.00.11.1 (workspace-shared version) — this is a backwards-compatible bug fix (fix:), no public API/behavior change beyond making the Windows update path actually work.

Co-Authored-By: Claude noreply@anthropic.com

`digstore update` on Windows returned NotFound because it called
select_installer_asset, which looked for a bundled `*-setup.exe`/`.msi`
GUI installer. That installer moved to dig-installer and digstore's own
releases no longer publish one, so the lookup always found nothing.

Unify the Windows path with the existing macOS/Linux self-replace path:
resolve the raw `digstore-<ver>-windows-x64.exe` binary via
select_binary_asset, download it, then atomically self-replace via
install_binary. Windows needs an extra step here that Unix doesn't:
overwriting the currently-running process's own image file fails
directly ("Access is denied", os error 5), so install_binary now
renames the running binary aside first, moves the new one into place,
then best-effort deletes the old one.

Removes the now-dead select_installer_asset/select_windows_installer/
download_asset/launch_installer GUI-installer helpers and their tests.

Regression test spawns a copy of a system executable and replaces it
while the child process is executing it, reproducing the exact lock
digstore hits when updating itself.

Closes #303

Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d MichaelTaylor3d merged commit 4e7502d into main Jul 11, 2026
10 checks passed
@MichaelTaylor3d MichaelTaylor3d deleted the fix/303-windows-self-update branch July 11, 2026 09:24
dkackman pushed a commit to dkackman/digstore that referenced this pull request Jul 11, 2026
… (Wave-1 DIG-Network#5/DIG-Network#6/DIG-Network#13/DIG-Network#14)

Close the biggest journey gaps before a developer ever spends DIG. Everything in
this slice is FREE — no wallet, no chain, no spend — so a developer can scaffold,
preview through the real read path, and preview cost before the one paid step.

DIG-Network#5 `digstore new <template>` — a free, no-mint scaffolder (today the only on-ramp,
`init`, mints 100 DIG into an empty dir). Five templates embedded in the binary
(include_str!): static-site, vite-react, next-static, nft-drop, dapp-window-chia.
Each writes a runnable local project — a `dig.toml`, a starter app, and (dapp/NFT)
a `window.chia` usage example. Refuses a non-empty dir without --force; creates no
`.dig` and never touches chain.

DIG-Network#6 `digstore dev` — the local inner loop: build-on-save + serve the REAL dig://
read path locally (init_store → add → commit → host runtime → merkle-verify →
AES-GCM-decrypt, the same plumbing as compile/cat), with live reload + an injected
dev `window.chia` shim. So "renders under dev" == "renders after deploy". Poll-based
watcher (no notify dep); multi-thread tokio runtime so a page's asset burst doesn't
stall; SPA fallback for routes but a true 404 for missing assets; shims injected
only into HTML at request time (never baked into the served bytes).

DIG-Network#13 `digstore doctor` + `commit --dry-run` — `doctor` runs pre-publish checks
(seed present/unlocked, funds vs 100 DIG + XCH fee, dighub login, default remote
reachable, content dir exists) as pass/fail, exits non-zero on a hard fail, never
spends. `commit --dry-run` computes + prints the resulting version (root) and the
exact DIG/XCH cost with NO seed unlock, NO wallet scan, NO anchor, NO finalize.

DIG-Network#14 task-first CLI help — one-line `about` strings lead with the task (commit =
"Publish your staged files as a new version"); the commit success line is now a
plain "Published a new version — it's live and permanent." with the capsule id
below it and the module/coin protocol detail behind --verbose.

Shared `dig.toml` reader extracted to `dig_toml::DigToml` (deploy + dev + doctor;
removes deploy's private copy). Templates/assets embedded via include_str!.

TDD: failing tests first throughout. 178 lib tests + new integration suites
(cli_new, cli_dev, cli_doctor, cli_commit_dryrun, cli_help additions) green
against the installed binary; cargo fmt + clippy -D warnings clean. Guest wasm
built and binary reinstalled per digstore discipline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjQgGAisBupqs7vpkmUhuN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant